package com.metier.persistance;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;

import com.donnees.dao.AbstractDAO;
import com.donnees.dao.DAOFactory;
import com.metier.logique.MSG;

/**
 * @name Parcours
 * @description Classe représentant un Parcours, implémente Serializable lui permettant d'être sérialisée c'est à dire qu'il peut être envoyé via le réseau, dans un fichier, etc.
 * 				http://ydisanto.developpez.com/tutoriels/java/serialisation-binaire/
 * @author Ambroise
 * @since 12/03/2012
 */
public class Image implements IPersistance, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private BigDecimal idImage;
	private String nom;
	private String url;


	private DAOFactory MysqlFactory;
	private AbstractDAO<Image> DAO;
	private String table = "image";
	
	/**
	 * @name Image
	 * @description Constructeur simple. Utilise le DAO configuré par défaut dans ConfigurationProjet.DEFAULT_DAO. 
	 */	
	public Image(){
		this.MysqlFactory = DAOFactory.getDAOFactory(DAOFactory.MYSQL);
		this.DAO = (AbstractDAO<Image>) this.MysqlFactory.getImageDAO();
	}

	/**
	 * @name find
	 * @description Méthode find permettant d'appeler des méthodes spécifiques selon l'argument "method" du MSG.<br />
	 * 				Le champ "method" du MSG défini la méthode qui sera exécutée. Par défaut findAll.<br />
	 * 				Méthodes:<br />
	 * 					findAll - Récupère tous les enregistrements de la table associée.<br />
	 * 					findById - Récupère l'enregistrement dont l'ID correspond à "id" du MSG. (Nécessite "id").<br />
	 * 					findByName - Récupère tous les enregistrements dont la colonne NOM contient "chaine" (Nécessite "chaine" et "typeResearch")<br />
	 * 
	 *	Exemple:
		Image Image = new Image();
	 	MSG oMSGParam = new MSG("method", "findById");
		oMSGParam.setData("id", 1);
		System.out.println(Image.find(oMSGParam).getData("donnees").toString());
		
		Exemple findAll:
		Image Image = new Image();
		MSG oMSG = Image.find(new MSG("method", "findAll"));
		System.out.println(oMSG.getData("donnees").toString());
		
		Exemple findByName:
		Image Image = new Image();
		MSG oMSG = new MSG();
		oMSG.setData("method", "findByName");
		oMSG.setData("chaine", "Test");
		oMSG = Image.find(oMSG);
		System.out.println(oMSG.getData("donnees").toString());
		
		
	 * @param 	oMSG -> Dans "donnees" se trouvent les résultats de la requête sql.
	 * 					Dans "typeDonnees" se trouve le type de résultat de la requête. (Liste d'entité, entité unique ou null si pas de résultat). (list, object, null)
	 */
	@Override
	public MSG find(MSG oMSG) {

		if(oMSG.getData("method") == "findAll" || oMSG.getData("method") == null){
			// Méthode findAll:
			MSG oMSGConfig = new MSG();
			oMSGConfig.setData("from", "FROM " + this.table);
			oMSG = this.DAO.findAll(oMSGConfig);
			
		}else if(oMSG.getData("method") == "findById"){
			// Méthode findById:
			if(oMSG.getData("id") != null){
				Object[] parametresInconnus = new Object[1];
				parametresInconnus[0] = oMSG.getData("id");
				
				MSG oMSGConfig = new MSG();
				oMSGConfig.setData("parametresInconnus", parametresInconnus);
				oMSGConfig.setData("select", "SELECT *");
				oMSGConfig.setData("from", "FROM " + this.table);
				oMSGConfig.setData("where", "WHERE ID_IMAGE = ?");
				oMSG = this.DAO.find(oMSGConfig);
			}else{
				JOptionPane.showMessageDialog(null, "Erreur lors de l'exécution de la méthode "+this.getClass().getSimpleName()+".find('findById'). L'argument 'id' est obligatoire.", "Arguments manquants", JOptionPane.ERROR_MESSAGE);
			}
			
		}else if(oMSG.getData("method") == "findByName"){
			if(oMSG.getData("chaine") != null){
				// Méthode findByName:
				Object[] parametresInconnus = new Object[1];
				parametresInconnus[0] = oMSG.getData("chaine");
				
				MSG oMSGConfig = new MSG();
				oMSGConfig.setData("parametresInconnus", parametresInconnus);
				oMSGConfig.setData("select", "SELECT *");
				oMSGConfig.setData("from", "FROM " + this.table);
				oMSGConfig.setData("where", "WHERE NOM LIKE ?");
				oMSGConfig.setData("orderBy", "ORDER BY NOM");
				oMSG = this.DAO.find(oMSGConfig);
			}else{
				JOptionPane.showMessageDialog(null, "Erreur lors de l'exécution de la méthode "+this.getClass().getSimpleName()+".find('findByName'). L'argument 'chaine' est obligatoire.", "Arguments manquants", JOptionPane.ERROR_MESSAGE);
			}
		}
		
		return oMSG;
	}

	/**
	 * @name insert
	 * @description Méthode insert générique permettant d'ajouter uniquement les champs voulus. (Attention, certains champs sont demandés par la BDD, si vous 
	 * 				ne les précisez pas, un popup vous avertira du champ oublié)
	 * 
	 * // Exemple 1:
		System.out.println("\nCode modifié dans "+this.getClass().getSimpleName() + ".run()");
		MSG oMSGParam = new MSG();
		Image Image = new Image();
		
		oMSGParam.setData("method", "insert");
		oMSGParam.setData("NOM", "Icone_verte");
		oMSGParam.setData("URL", "http://googlemaps.googlermania.com/google_maps_api_v3/en/Google_Maps_Marker.png");
		
		MSG oMSG = Image.insert(oMSGParam);
		System.out.println("Dernier(s) ID inséré(s): " + oMSG.getData("donnees") + ".\nType de données: " + oMSG.getData("typeDonnees"));
		
	 * @return {@link MSG} MSG contenant toutes les informations concernant les résultats.<br />
	 * 			"donnees" -> Liste de BigDecimal correspondants aux IDs insérés. Ou BigDecimal correspondant à l'ID inséré.
	 * 			"typeDonnees" -> Type de données retournée: List ("List"), BigDecimal ("BigDecimal") ou null ("0")
	 */
	@Override
	public MSG insert(MSG oMSG) {			
			String[] colonnes = {"ID_IMAGE", "NOM", "URL"};
			int nbColonnes = colonnes.length;
			String champs = "";
			String values = "";
			boolean virgule = false;
			List<String> listParametresInconnus = new ArrayList<String>();

			// On contrôle les données recues.
			if(oMSG.getData("NOM") != null){
				// On supprime les tirets du 6 ainsi que les espaces inutiles.
				oMSG.setData("NOM", ((String)oMSG.getData("NOM")).replace("-", " ").trim());
			}
			
			// On crée la requête.
			for(int i = 0; i < nbColonnes; i++){
					if(oMSG.getData(colonnes[i]) != null){

					if(virgule){
						champs+= ", ";
						values+= ", ";
					}
					// On rajoute le nom de la table dans le champs.
					champs+= colonnes[i];
					// On rajoute une valeur inconnue dans les valeurs.
					values+= "?";
					// On rajoute dans la liste des valeurs inconnues la valeur actuelle.
					listParametresInconnus.add(oMSG.getData(colonnes[i]).toString());
					// On a besoin de mettre une virgule au prochain coup pour séparer.
					virgule = true;
				}
			}
			
			// On traite la liste de manière à la convertir en tableau.
			Object[] parametresInconnus = new Object[listParametresInconnus.size()];
			
			int i = 0;
			for (Object object : listParametresInconnus) {
				parametresInconnus[i] = object.toString();
				i++;
			}

			MSG oMSGConfig = new MSG();
			oMSGConfig.setData("table", this.table);
			oMSGConfig.setData("champs", champs);
			oMSGConfig.setData("values", values);
			oMSGConfig.setData("parametresInconnus", parametresInconnus);

			oMSG = this.DAO.insert(oMSGConfig);
					
		return oMSG;
	}

	/**
	 * @name update
	 * @description Méthode update générique permettant de modifier les éléments voulus.
	 * 				"id" doit contenir l'id pour lequel la modification doit être faite.
	 * Exemple:
			System.out.println("\nCode modifié dans "+this.getClass().getSimpleName() + ".run()");
			MSG oMSGParam = new MSG();
			Image Image = new Image();
			
			oMSGParam.setData("NOM", "Icone_simple");
			oMSGParam.setData("URL", "http://googlemaps.googlermania.com/google_maps_api_v3/en/Google_Maps_Marker.png");
			oMSGParam.setData("id", "1");
		
			MSG oMSG = Image.update(oMSGParam);
	 * @return {@link MSG} MSG contenant toutes les informations concernant les résultats.<br />
	 * 			"donnees" -> Booléen indiquant si l'update a été fait. (true -> la requête a été exécutée)
	 * 			"typeDonnees" -> "bool"
	 */
	@Override
	public MSG update(MSG oMSG) {
			String[] colonnes = {"NOM", "URL"};
			int nbColonnes = colonnes.length;
			String set = "";
			boolean virgule = false;
			List<String> listParametresInconnus = new ArrayList<String>();

			// On contrôle les données recues.
			if(oMSG.getData("NOM") != null){
				// On supprime les tirets du 6 ainsi que les espaces inutiles.
				oMSG.setData("NOM", ((String)oMSG.getData("NOM")).replace("-", " ").trim());
			}
			
			// On crée la requête.
			for(int i = 0; i < nbColonnes; i++){
					if(oMSG.getData(colonnes[i]) != null){

					if(virgule){
						set += ", ";
					}
					// On rajoute le nom de la table dans le champs.
					set+= colonnes[i] + " = ";
					// On rajoute une valeur inconnue dans les valeurs.
					set+= "?";
					// On rajoute dans la liste des valeurs inconnues la valeur actuelle.
					listParametresInconnus.add(oMSG.getData(colonnes[i]).toString());
					// On a besoin de mettre une virgule au prochain coup pour séparer.
					virgule = true;
				}
			}
			
			String where = "";
			if(oMSG.getData("method") == null || oMSG.getData("method") == "updateById"){
				// Comportement par défaut. Si on souhaite update un seul n-upplet.
				where = "ID_IMAGE = ?";
				listParametresInconnus.add(oMSG.getData("id").toString());
			}
			
			// On traite la liste de manière à la convertir en tableau.
			Object[] parametresInconnus = new Object[listParametresInconnus.size()];
			
			int i = 0;
			for (Object object : listParametresInconnus) {
				parametresInconnus[i] = object.toString();
				i++;
			}

			MSG oMSGConfig = new MSG();
			oMSGConfig.setData("table", this.table);
			oMSGConfig.setData("set", set);
			oMSGConfig.setData("where", where);
			oMSGConfig.setData("parametresInconnus", parametresInconnus);

			oMSG = this.DAO.update(oMSGConfig);		
		
		return oMSG;
	}

	/**
	 * @name delete
	 * @description Méthode delete générique permettant de supprimer les éléments voulus.
	 * 				"id" doit contenir l'id pour lequel la suppression doit être faite.
	 * Exemple:
			 	System.out.println("\nCode modifié dans "+this.getClass().getSimpleName() + ".run()");
				Image Image = new Image();
				
				
				MSG oMSG = new MSG();
				oMSG.setData("method", "deleteById");
				oMSG.setData("id", "2");
				
				oMSG = Image.delete(oMSG);
	 * @return {@link MSG} MSG contenant toutes les informations concernant les résultats.<br />
	 * 			"donnees" -> Booléen indiquant si le delete a été fait. (true -> la requête a été exécutée)
	 * 			"typeDonnees" -> "bool"
	 */
	@Override
	public MSG delete(MSG oMSG) {
		// Méthode delete
		if(oMSG.getData("method") == "deleteById" || oMSG.getData("method") == null){
			
			String where = "ID_IMAGE = ?";
			
			// On met l'id dans les paramètres.
			Object[] parametresInconnus = new Object[1];
			parametresInconnus[0] = oMSG.getData("id");
			
			MSG oMSGConfig = new MSG();
			oMSGConfig.setData("table", this.table);
			oMSGConfig.setData("where", where);
			oMSGConfig.setData("parametresInconnus", parametresInconnus);
			
			oMSG = this.DAO.delete(oMSGConfig);
			
		}
		
		return oMSG;
	}

	@Override
	public String toString() {
		return "Image [idImage=" + this.idImage + ", nom=" + this.nom
				+ ", url=" + this.url + "]";
	}

	public BigDecimal getIdImage() {
		return this.idImage;
	}

	public void setIdImage(BigDecimal idImage) {
		this.idImage = idImage;
	}

	public String getNom() {
		return this.nom;
	}

	public void setNom(String nom) {
		this.nom = nom;
	}

	public String getUrl() {
		return this.url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

}